package org.wattdepot.gdata.kukuicup.updater.energybaselines;

import java.net.URL;
import java.text.SimpleDateFormat;
import javax.xml.datatype.XMLGregorianCalendar;
import org.wattdepot.client.WattDepotClient;
import org.wattdepot.client.WattDepotClientException;
import org.wattdepot.gdata.kukuicup.service.GDataBatchRequest;
import org.wattdepot.gdata.kukuicup.service.GDataService;
import org.wattdepot.gdata.kukuicup.service.WattDepotService;
import org.wattdepot.gdata.kukuicup.updater.GDataTask;
import org.wattdepot.util.tstamp.Tstamp;
import java.util.Locale;

/**
 * Collects hourly energy data for the baseline period and writes it out to the spreadsheet.
 * 
 * @author Philip Johnson
 */
public class HourlyEnergyBaselinesTask extends GDataTask {

  private static final String startDateKey = "hourly.energy.baselines.start.date";
  private static final String endDateKey = "hourly.energy.baselines.end.date";
  private XMLGregorianCalendar startHour;
  private XMLGregorianCalendar endHour;
  private String startString;
  private String endString;
  private String sourceName;

  /**
   * Creates the new HourlyEnergyBaselinesTask.
   * 
   * @param wattDepotService The WattDepot service configuration data.
   * @param gdataService The gdata service configuration data.
   * @param spreadsheetURL The URL to the spreadsheet containing the data.
   * @param sourceName The WattDepot source of interest.
   * @param isVirtual True if the source is virtual.
   * @param row The row in the spreadsheet that this source's data appears in.
   */
  public HourlyEnergyBaselinesTask(WattDepotService wattDepotService, GDataService gdataService,
      URL spreadsheetURL, String sourceName, boolean isVirtual, int row) {
    super(wattDepotService, gdataService, spreadsheetURL, sourceName, row, "HourlyEnergyBaselines",
        isVirtual);
    this.sourceName = sourceName;
    this.startString = wattDepotService.getProperties().getRequiredProperty(startDateKey);
    this.endString = wattDepotService.getProperties().getRequiredProperty(endDateKey);
    SimpleDateFormat dateFormat = new SimpleDateFormat("MM/dd/yyyy", Locale.US);
    XMLGregorianCalendar endDate;
    try {
      this.startHour = Tstamp.makeTimestamp(dateFormat.parse(startString).getTime());
      endDate = Tstamp.makeTimestamp(dateFormat.parse(endString).getTime());
    }
    catch (Exception e) {
      throw new RuntimeException("Error parsing hourlyenergybaseline start or end date.", e);
    }
    this.endHour = Tstamp.incrementHours(endDate, 23);
  }

  /**
   * Collects the hourly baseline data and updates the spreadsheet.
   */
  @Override
  public void run() {
    // System.out.format("Startup: %s, %s, %s%n", sourceName, this.startDate, this.endDate);
    WattDepotClient client = this.wattDepotService.getClient();
    BaselineDataSet dataSet = new BaselineDataSet();

    startWattDepotTiming();

    // Loop through all hours between startHour and endHour.
    for (XMLGregorianCalendar beginningOfHour = this.startHour; 
         beginningOfHour.toGregorianCalendar().getTimeInMillis() <= 
           this.endHour.toGregorianCalendar().getTimeInMillis(); 
         beginningOfHour = Tstamp.incrementHours(beginningOfHour, 1)) {
      XMLGregorianCalendar endingOfHour = Tstamp.incrementHours(beginningOfHour, 1);
      Integer energy = 0;
      try {
        energy = (int) client.getEnergyConsumed(sourceName, beginningOfHour, endingOfHour, 10);
        // Get the index into the baseline data structure. 
        int index = BaselineDataSet.convertDateToHourlyIndex(beginningOfHour);
        //System.out.format("Found energy %s for %s at %s%n", energy, sourceName, beginningOfHour);
        dataSet.add(index, energy);
      }
      catch (WattDepotClientException e) {
        System.out.format("Failed to get energy for %s for %s%n", sourceName, beginningOfHour);
      }

    }

    stopWattDepotTiming();

    try {
      startGDataTiming();
      // Now update the spreadsheet with all of the data.
      GDataBatchRequest request = new GDataBatchRequest(gdataService, spreadsheetURL);
      // Update the lastUpdate cell
      request.addRequest(this.row, 2, gdataService.makeLastUpdate());
      // Update the start and end date cells
      request.addRequest(this.row, 3, this.startString);
      request.addRequest(this.row, 4, this.endString);

      // Update the remaining columns with the hourly baseline data.
      int column = 5;
      for (int index = 0; index < (7 * 24); index++) {
        String baseline = String.valueOf((int) dataSet.getAverage(index));
        request.addRequest(this.row, column, baseline);
        column++;
      }
      request.sendRequest();
      stopGDataTiming();
      String numBaselines = String.valueOf(dataSet.getTotalEntries());
      printTaskResults(numBaselines + " baselines", "kWh", "OK");
    }
    catch (Exception e) {
      System.out.format("Problem getting baseline for source %s: %s%n", sourceName, e.getMessage());
    }

  }

}
